#ifndef _MEMORY_STORAGE_H
#define _MEMORY_STORAGE_H

#include <unordered_set>
#include <functional>
#include <list>
#include <set>
#include <map>
#include "istorage.h"
#include "FSBAllocator.hh"

struct MemoryStorageChunk : public StorageChunk {
	size_t size_;
	char *mem_;
	std::multimap<size_t, MemoryStorageChunk*>::iterator sizes_i_;
};

struct MemoryStorageChunkCompareAddrs {
	bool operator()(MemoryStorageChunk* const& lhs,
	    MemoryStorageChunk* const & rhs) {
		my_assert(lhs && rhs);
		return lhs->mem_ < rhs->mem_;
	}
};

struct MemoryStorageChunkCompareSizes {
	bool operator()(MemoryStorageChunk* const& lhs,
	    MemoryStorageChunk* const& rhs) {
		my_assert(lhs && rhs);
		return lhs->size_ < rhs->size_;
	}
};


class MemoryStorage : public IStorage {
	public:

	typedef std::multimap<char*, MemoryStorageChunk* //>, MemoryStorageChunkCompareAddrs
	>//	    FSBAllocator<MemoryStorageChunk*>>
	    ChunkAddrsSet;
	typedef std::multimap<size_t, MemoryStorageChunk* //, MemoryStorageChunkCompareSizes
	>//	    FSBAllocator<MemoryStorageChunk*>>
	    ChunkSizesSet;

	MemoryStorage() = delete;
	MemoryStorage(uint64_t size, bool addresses_are_virtual = false);
	virtual ~MemoryStorage();

	virtual StorageChunk *Alloc(uint64_t size,
	    const std::list<StorageChunk**, FSBAllocator<StorageChunk**>>& currently_unused,
	    std::function<void (StorageChunk**)> delete_func);
	virtual void *Load(StorageChunk *p_st_data);
	virtual void Free(StorageChunk *p_st_data);

	virtual void AssertOk();

	private:

	void EraseBySizesIt(ChunkSizesSet::iterator i);
	void EraseByAddrsIt(ChunkAddrsSet::iterator i);

	ChunkAddrsSet chunk_addrs_;
	ChunkSizesSet chunk_sizes_;

//	std::unordered_set<StorageChunk*> allocated_;
	std::set<StorageChunk*, std::less<StorageChunk*>, FSBAllocator<StorageChunk*>> allocated_;

	char *memory_;
	uint64_t size_;
	bool addresses_are_virtual_;
	static const uint64_t ARRANGEMENT_SIZE = 4096;
};


#endif // _MEMORY_STORAGE_H
